#include "../../common/CppMemPool.h"
#include "SQLiteTransaction.h"
#include "../SQLStr.h"
#include "SQLiteDatabase.h"
#include "SQLiteCommand.h"
#include "../../text/CFString.h"

namespace cppflib
{

namespace database
{

namespace sqlite
{


SQLiteTransaction::SQLiteTransaction(void)
{
   isCommitOK = false;
   pDB = NULL;
}

SQLiteTransaction::SQLiteTransaction(SQLiteDatabase * pDB)
{
   isCommitOK = false;
   this->pDB = pDB;
   cppmempool::Retain(this->pDB);
}

SQLiteTransaction::~SQLiteTransaction(void)
{
   Close();
}

/**
 *  Begin transaction with exclusive lock
 */
bool SQLiteTransaction::Begin()
{
   return Begin(SQLiteTransaction::EXCLUSIVE);
}

/**
 *  Begin transaction with a specific lock
 */
bool SQLiteTransaction::Begin(SQLiteTransaction::locktype_t lockType)
{
   pcwstr_t strLockType = NULL;
   switch (lockType) {
      case SQLiteTransaction::DEFERRED: strLockType = _S("DEFERRED"); break;
      case SQLiteTransaction::EXCLUSIVE: strLockType = _S("EXCLUSIVE"); break;
      case SQLiteTransaction::IMMEDIATE: strLockType = _S("IMMEDIATE"); break;   
   }

   CFString beginCmd;
   beginCmd.Format(_S("BEGIN %s TRANSACTION"), strLockType);

   SQLiteCommand cmd(pDB);
   cmd.SetQueryString(beginCmd);
   return cmd.ExecNonQuery();
}

/**
 *  Set commit OK before calling 'End'
 */
void SQLiteTransaction::SetCommitOK()
{
   isCommitOK = true;
}

/**
 *  End transaction
 */
bool SQLiteTransaction::End()
{
   SQLiteCommand cmd(pDB);
   cmd.SetQueryString(isCommitOK ? CFString("COMMIT") : CFString("ROLLBACK"));
   return cmd.ExecNonQuery();
}

/**
 *  Release any resource
 */
void SQLiteTransaction::Close()
{
   isCommitOK = false;

   if (pDB) {
      cppmempool::Release(pDB);
      pDB = NULL;
   }
}


} // end of namespace sqlite

} // end of namespace database

} // end of namespace cppflib
